﻿using Red.Controls.ViewModels;
using System;
using System.Linq;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows.Controls;
using System.Windows;

namespace Red.Controls
{
    /// <summary>
    /// Interaction logic for CheckedListBox.xaml
    /// </summary>
    /// 
    public class CheckboxValueChangedEventArgs : PropertyChangedEventArgs
    {
        public CheckedListBoxItemViewModel Item { get; set; }

        public CheckboxValueChangedEventArgs() : base( "CollectionItemCheckbox" ) { }
    }

    public partial class CheckedListBox : UserControl, INotifyPropertyChanged
    {
#region Properties
        private bool _checkAllOperationInProgress;

        private ObservableCollection<CheckedListBoxItemViewModel> _itemsCollection;
        public ObservableCollection< CheckedListBoxItemViewModel > ItemsCollection 
        {
            get
            {
                return _itemsCollection;
            }
            set 
            {
                _itemsCollection.Clear();
                foreach ( CheckedListBoxItemViewModel item in value )
                {
                    _itemsCollection.Add( item );
                }
                CheckAllCheckBox.Visibility = _itemsCollection.Count > 1 ? Visibility.Visible : Visibility.Collapsed;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
#endregion

#region Constructor
        public CheckedListBox()
        {
            InitializeComponent();

            _checkAllOperationInProgress = false;
            _itemsCollection = new ObservableCollection<CheckedListBoxItemViewModel>();
            _itemsCollection.CollectionChanged += ItemsCollectionChanged;
            DataContext = this;
        }
#endregion Constructor

#region Event handlers
        private void ItemsCollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e )
        {
            if ( e.Action == NotifyCollectionChangedAction.Remove )
            {
                foreach ( CheckedListBoxItemViewModel item in e.OldItems )
                {
                    item.PropertyChanged -= CollectionItemPropertyChanged;
                }
            }
            else if ( e.Action == NotifyCollectionChangedAction.Add )
            {
                foreach ( CheckedListBoxItemViewModel item in e.NewItems )
                {
                    item.PropertyChanged += CollectionItemPropertyChanged;
                }
            }  
        }

        private void CollectionItemPropertyChanged( object sender, PropertyChangedEventArgs e )
        {
            int index = _itemsCollection.IndexOf( sender as CheckedListBoxItemViewModel );
            if ( index >= 0 && PropertyChanged != null )
            {
                CheckboxValueChangedEventArgs newArgs = new CheckboxValueChangedEventArgs();
                newArgs.Item = sender as CheckedListBoxItemViewModel;
                PropertyChanged( this, newArgs );
            }

            if ( !_checkAllOperationInProgress )
            {
                CheckedListBoxItemViewModel found = _itemsCollection.FirstOrDefault( item => item.IsChecked == false );
                bool allChecked = ( found == null ) ? true : false;
                if ( allChecked != CheckAllCheckBox.IsChecked )
                {
                    CheckAllCheckBox.IsChecked = allChecked;
                }
            }
        }

        // set flag _checkAllOperationInProgress so that CollectionItemPropertyChanged() above 
        // won't update checkAll checkbox state if PropertyChanged event was fired by the CheckAll_Checked/Unchecked
        private void CheckAllCheckBox_Click( object sender, RoutedEventArgs e )
        {
            bool shouldBeChecked = CheckAllCheckBox.IsChecked.HasValue && CheckAllCheckBox.IsChecked.Value;

            _checkAllOperationInProgress = true;
            foreach ( CheckedListBoxItemViewModel item in _itemsCollection )
            {
                if ( item.IsChecked != shouldBeChecked )
                {
                    item.IsChecked = shouldBeChecked;
                }
            }
            _checkAllOperationInProgress = false;
        }
#endregion Event handlers
    }
}
